package org.jsola.hr.service.impl;

import groovy.lang.Lazy;
import lombok.extern.slf4j.Slf4j;
import org.jsola.admin.entity.SiteDO;
import org.jsola.admin.vo.HeaderFieldsTemplateListVO;
import org.jsola.common.StrKit;
import org.jsola.contract.entity.TemplateDO;
import org.jsola.core.Page;
import org.jsola.core.entity.BaseCreateDO;
import org.jsola.core.entity.BaseDO;
import org.jsola.exception.ParamException;
import org.jsola.hr.common.EmpFieldModuleCodeKit;
import org.jsola.hr.common.ExampleKit;
import org.jsola.hr.constant.HrConstants;
import org.jsola.hr.dao.ICompanyAdditionalFieldsDAO;
import org.jsola.hr.dto.CompanyAdditionalFieldsAddDTO;
import org.jsola.hr.dto.CompanyAdditionalFieldsUpdateDTO;
import org.jsola.hr.entity.*;
import org.jsola.hr.provider.IAdminProviderService;
import org.jsola.hr.provider.IContractProviderService;
import org.jsola.hr.query.CompanyAdditionalFieldsQuery;
import org.jsola.hr.query.CompanyNecessaryFieldQuery;
import org.jsola.hr.query.CustomTemplateFieldQuery;
import org.jsola.hr.service.*;
import org.jsola.hr.vo.CompanyAdditionalFieldsListVO;
import org.jsola.hr.vo.CompanyAdditionalFieldsVO;
import org.jsola.hr.vo.CustomTemplateFieldListVO;
import org.jsola.hr.vo.CustomTemplateVO;
import org.jsola.user.core.TokenUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * 公司员工额外字段表
 *
 * @author zhr
 */
@Service("hrCompanyAdditionalFieldsServiceImpl")
@Slf4j
public class CompanyAdditionalFieldsServiceImpl implements ICompanyAdditionalFieldsService {

    @Autowired
    private ICompanyAdditionalFieldsDAO companyAdditionalFieldsDAO;

    @Autowired
    private IEmpAdditionalFieldsService empAdditionalFieldsService;

    @Autowired
    private ICompanyNecessaryFieldService companyNecessaryFieldService;

    @Autowired
    @Lazy
    private ICustomTemplateService customTemplateService;

    @Autowired
    private ICustomTemplateFieldService customTemplateFieldService;

    @Autowired
    private IContractProviderService contractProviderService;

    @Autowired
    private ISocProgService socProgService;

    @Autowired
    private IAdminProviderService adminProviderService;

    @Autowired
    private ICompanyService companyService;

    /**
     * 选项
     */
    private static final Integer FIELD_TYPE_OPTION = 1;

    /**
     * 单行文本
     */
    private static final Integer FIELD_TYPE_TEXT = 2;

    /**
     * 日期类型
     */
    private static final Integer FIELD_TYPE_DATE = 3;

    /**
     * 长文本类型
     */
    private static final Integer FIELD_TYPE_TEXTAREA = 4;

    /**
     * 花名册字段模块名
     */
    private static final String EMP_INFO_BY_COMPANY = "empInfoByCompany";

    @Override
    public Integer querySalaryHead(String companyId, TokenUser tokenUser) {
        //花名册表头查询

        CompanyAdditionalFieldsQuery companyAdditionalFieldsQuery = new CompanyAdditionalFieldsQuery();
        companyAdditionalFieldsQuery.setCompanyId(companyId);
        companyAdditionalFieldsQuery.setModuleCode("月工资表列表");
        List<CompanyAdditionalFieldsListVO> select = select(companyAdditionalFieldsQuery, tokenUser.getSiteId());
        if (CollectionUtils.isEmpty(select)) {
            //表头初始化
            for (int i = 0; i < 13; i++) {
                CompanyAdditionalFieldsAddDTO companyAdditionalFieldsAddDTO = new CompanyAdditionalFieldsAddDTO();
                companyAdditionalFieldsAddDTO.setFieldType(2);
                companyAdditionalFieldsAddDTO.setModuleCode("月工资表列表");
                companyAdditionalFieldsAddDTO.setCompanyId(companyId);
                companyAdditionalFieldsAddDTO.setSort(i);
                companyAdditionalFieldsAddDTO.setIsOpen(true);
                companyAdditionalFieldsAddDTO.setIsEdit(1);
                if (i == 0) {
                    companyAdditionalFieldsAddDTO.setIsEdit(0);
                    companyAdditionalFieldsAddDTO.setFieldName("姓名");
                    companyAdditionalFieldsAddDTO.setDescription("empName");
                } else if (i == 1) {
                    companyAdditionalFieldsAddDTO.setIsEdit(0);
                    companyAdditionalFieldsAddDTO.setFieldName("身份证");
                    companyAdditionalFieldsAddDTO.setDescription("idCard");
                } else if (i == 2) {
                    companyAdditionalFieldsAddDTO.setFieldName("工时");
                    companyAdditionalFieldsAddDTO.setDescription("workTime");
                } else if (i == 3) {
                    companyAdditionalFieldsAddDTO.setFieldName("基本工资");
                    companyAdditionalFieldsAddDTO.setDescription("fixedSalarySum");
                } else if (i == 4) {
                    companyAdditionalFieldsAddDTO.setFieldName("一次性费用");
                    companyAdditionalFieldsAddDTO.setDescription("oneTimeFee");
                } else if (i == 5) {
                    companyAdditionalFieldsAddDTO.setFieldName("出勤天数");
                    companyAdditionalFieldsAddDTO.setDescription("workDay");
                } else if (i == 6) {
                    companyAdditionalFieldsAddDTO.setFieldName("应发工资");
                    companyAdditionalFieldsAddDTO.setDescription("shouldWages");
                } else if (i == 7) {
                    companyAdditionalFieldsAddDTO.setFieldName("个人社保");
                    companyAdditionalFieldsAddDTO.setDescription("empSocialSecurity");
                } else if (i == 8) {
                    companyAdditionalFieldsAddDTO.setFieldName("企业社保");
                    companyAdditionalFieldsAddDTO.setDescription("enterpriseSocialSecurity");
                } else if (i == 9) {
                    companyAdditionalFieldsAddDTO.setFieldName("个人公积金");
                    companyAdditionalFieldsAddDTO.setDescription("empProvidentFund");
                } else if (i == 10) {
                    companyAdditionalFieldsAddDTO.setFieldName("企业公积金");
                    companyAdditionalFieldsAddDTO.setDescription("enterpriseProvidentFund");
                } else if (i == 11) {
                    companyAdditionalFieldsAddDTO.setFieldName("个人所得税");
                    companyAdditionalFieldsAddDTO.setDescription("tax");
                } else if (i == 12) {
                    companyAdditionalFieldsAddDTO.setFieldName("实发工资");
                    companyAdditionalFieldsAddDTO.setDescription("paidWages");
                }

                save(companyAdditionalFieldsAddDTO.to(CompanyAdditionalFieldsDO.class), tokenUser.getSiteId(), tokenUser.getUserId());
            }
            //不可见表头

        }

        return 1;
    }

    @Override
    public Integer updateHead(CompanyAdditionalFieldsQuery companyAdditionalFieldsQuery, TokenUser tokenUser) {
        List<CompanyAdditionalFieldsDO> select = selectDO(companyAdditionalFieldsQuery, tokenUser.getSiteId());
        Map<String, CompanyAdditionalFieldsDO> map = select.stream().collect(Collectors.toMap(CompanyAdditionalFieldsDO::getFieldName, p -> p));
        for (int i = 0; i < companyAdditionalFieldsQuery.getCanSee().size(); i++) {
            CompanyAdditionalFieldsUpdateDTO companyAdditionalFieldsUpdateDTO = new CompanyAdditionalFieldsUpdateDTO();
            companyAdditionalFieldsUpdateDTO.setId(map.get(companyAdditionalFieldsQuery.getCanSee().get(i)).getId());
            companyAdditionalFieldsUpdateDTO.setIsOpen(true);
            companyAdditionalFieldsUpdateDTO.setSort(i);
            updateByIdSelective(companyAdditionalFieldsUpdateDTO.to(CompanyAdditionalFieldsDO.class), tokenUser.getSiteId(), tokenUser.getUserId());
        }

        for (int i = 0; i < companyAdditionalFieldsQuery.getIgnore().size(); i++) {
            CompanyAdditionalFieldsUpdateDTO companyAdditionalFieldsUpdateDTO = new CompanyAdditionalFieldsUpdateDTO();
            companyAdditionalFieldsUpdateDTO.setId(map.get(companyAdditionalFieldsQuery.getIgnore().get(i)).getId());
            companyAdditionalFieldsUpdateDTO.setIsOpen(false);
            companyAdditionalFieldsUpdateDTO.setSort(i);
            updateByIdSelective(companyAdditionalFieldsUpdateDTO.to(CompanyAdditionalFieldsDO.class), tokenUser.getSiteId(), tokenUser.getUserId());
        }

        return 1;
    }

    @Override
    public CompanyAdditionalFieldsListVO getHead(CompanyAdditionalFieldsQuery companyAdditionalFieldsQuery, TokenUser tokenUser) {
        List<CompanyAdditionalFieldsListVO> canSee = new ArrayList<>();
        List<CompanyAdditionalFieldsListVO> ignore = new ArrayList<>();
        List<CompanyAdditionalFieldsListVO> select = select(companyAdditionalFieldsQuery, tokenUser.getSiteId());
        for (CompanyAdditionalFieldsListVO companyAdditionalFieldsListVO : select) {
            if (companyAdditionalFieldsListVO.getIsOpen()) {
                canSee.add(companyAdditionalFieldsListVO);
            } else {
                ignore.add(companyAdditionalFieldsListVO);
            }
        }
        CompanyAdditionalFieldsListVO companyAdditionalFieldsListVO = new CompanyAdditionalFieldsListVO();
        companyAdditionalFieldsListVO.setCanSee(canSee);
        companyAdditionalFieldsListVO.setIgnore(ignore);
        return companyAdditionalFieldsListVO;
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public CompanyAdditionalFieldsVO save(CompanyAdditionalFieldsAddDTO companyAdditionalFieldsAddDTO, TokenUser tokenUser) {
        //花名册添加员工字段时校验是否和公司下社保子项重复
        if (!StringUtils.isEmpty(companyAdditionalFieldsAddDTO.getCompanyId())) {
            if (socProgService.checkEmpItemName(companyAdditionalFieldsAddDTO.getCompanyId(), companyAdditionalFieldsAddDTO.getFieldName(), tokenUser)) {
                throw new ParamException("公司下社保子项存在相同的字段名");
            }
        }
        //校验模板花名册中是否已存在该字段
        List<HeaderFieldsTemplateListVO> headerFieldsTemplateDOList = adminProviderService.selectHeaderByModuleAndName(EMP_INFO_BY_COMPANY, companyAdditionalFieldsAddDTO.getFieldName());
        ParamException.isTrue(CollectionUtils.isEmpty(headerFieldsTemplateDOList), "字段已在花名册模板字段中使用");
        checkFieldsForSave(companyAdditionalFieldsAddDTO);
        // 校验员工设置 hr_company_necessary_field表重复字段 花名册自定义字段与花名册所有模块基础字段名称不重复
        List<CompanyNecessaryFieldDO> companyNecessaryFieldDOList =
                companyNecessaryFieldService.selectByModuleAndFiledName(null
                        , companyAdditionalFieldsAddDTO.getFieldName(), companyAdditionalFieldsAddDTO.getCompanyId());
        if (!CollectionUtils.isEmpty(companyNecessaryFieldDOList)) {
            throw new ParamException("当前模块下存在相同的字段名");
        }
        // 转DO
        CompanyAdditionalFieldsDO companyAdditionalFieldsDO = companyAdditionalFieldsAddDTO.to(CompanyAdditionalFieldsDO.class);
        // 保存
        companyAdditionalFieldsDO = save(companyAdditionalFieldsDO, tokenUser.getSiteId(), tokenUser.getUserId());
        return companyAdditionalFieldsDO.to(CompanyAdditionalFieldsVO.class);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public List<CompanyAdditionalFieldsVO> batchSave(List<CompanyAdditionalFieldsAddDTO> companyAdditionalFieldsAddDTOList, TokenUser tokenUser) {
        if (CollectionUtils.isEmpty(companyAdditionalFieldsAddDTOList)) {
            return null;
        }
        List<CompanyAdditionalFieldsDO> companyAdditionalFieldsDOList = companyAdditionalFieldsAddDTOList
                .parallelStream()
                .map(companyAdditionalFieldsAddDTO -> {
                    CompanyAdditionalFieldsDO companyAdditionalFieldsDO = companyAdditionalFieldsAddDTO.to(CompanyAdditionalFieldsDO.class);
                    companyAdditionalFieldsDO.preInsert(tokenUser.getUserId());
                    companyAdditionalFieldsDO.setSiteId(tokenUser.getSiteId());
                    return companyAdditionalFieldsDO;
                }).collect(Collectors.toList());
        companyAdditionalFieldsDAO.insertListAndSetId(companyAdditionalFieldsDOList);
        return companyAdditionalFieldsDOList
                .parallelStream()
                .map(companyAdditionalFieldsDO -> companyAdditionalFieldsDO.to(CompanyAdditionalFieldsVO.class))
                .collect(Collectors.toList());
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public CompanyAdditionalFieldsVO save2(CompanyAdditionalFieldsAddDTO companyAdditionalFieldsAddDTO, TokenUser tokenUser) {
        ParamException.isTrue(org.apache.commons.lang3.StringUtils.isNotBlank(companyAdditionalFieldsAddDTO.getFieldName())
                , "字段名称不能为空或纯空格");
        companyAdditionalFieldsAddDTO.setFieldName(companyAdditionalFieldsAddDTO.getFieldName().trim());
        companyAdditionalFieldsAddDTO.setIsOpen(Boolean.TRUE);
        companyAdditionalFieldsAddDTO.setIsEdit(1);
        companyAdditionalFieldsAddDTO.setIsNecessary(Boolean.FALSE);
        //花名册添加员工字段时校验是否和公司下社保子项重复
        if (!StringUtils.isEmpty(companyAdditionalFieldsAddDTO.getCompanyId())) {
            if (socProgService.checkEmpItemName(companyAdditionalFieldsAddDTO.getCompanyId(), companyAdditionalFieldsAddDTO.getFieldName(), tokenUser)) {
                throw new ParamException("公司下社保子项存在相同的字段名");
            }
        }
        //校验模板花名册中是否已存在该字段
        List<HeaderFieldsTemplateListVO> headerFieldsTemplateDOList = adminProviderService.selectHeaderByModuleAndName(EMP_INFO_BY_COMPANY, companyAdditionalFieldsAddDTO.getFieldName());
        ParamException.isTrue(CollectionUtils.isEmpty(headerFieldsTemplateDOList), "字段已在花名册模板字段中使用");
        checkFieldsForSave(companyAdditionalFieldsAddDTO);
        // 校验员工设置 hr_company_necessary_field表重复字段 花名册自定义字段与花名册所有模块基础字段名称不重复
        List<CompanyNecessaryFieldDO> companyNecessaryFieldDOList =
                companyNecessaryFieldService.selectByModuleAndFiledName(null
                        , companyAdditionalFieldsAddDTO.getFieldName(), companyAdditionalFieldsAddDTO.getCompanyId());
        if (!CollectionUtils.isEmpty(companyNecessaryFieldDOList)) {
            throw new ParamException("当前模块下存在相同的字段名");
        }
        // 转DO 在租户下所有用工单位同步新增
        List<CompanyDO> companyDOList = companyService.selectBySiteId(tokenUser.getSiteId());
        List<CompanyAdditionalFieldsAddDTO> companyAdditionalFieldsAddDTOList = new ArrayList<>();
        for (CompanyDO companyDO : companyDOList) {
            CompanyAdditionalFieldsAddDTO additionalFieldsAddDTO
                    = companyAdditionalFieldsAddDTO.to(CompanyAdditionalFieldsAddDTO.class);
            additionalFieldsAddDTO.setCompanyId(companyDO.getId());
            companyAdditionalFieldsAddDTOList.add(additionalFieldsAddDTO);
        }
        // 新增租户级自定义
        CompanyAdditionalFieldsAddDTO siteFieldsAddDTO
                = companyAdditionalFieldsAddDTO.to(CompanyAdditionalFieldsAddDTO.class);
        siteFieldsAddDTO.setCompanyId("site");
        companyAdditionalFieldsAddDTOList.add(siteFieldsAddDTO);
        // 向租户预登记模板中也添加一份
        CompanyAdditionalFieldsAddDTO additionalFieldsAddDTO
                = companyAdditionalFieldsAddDTO.to(CompanyAdditionalFieldsAddDTO.class);
        additionalFieldsAddDTO.setCompanyId("site");
        additionalFieldsAddDTO.setModuleType("checkIn");
        additionalFieldsAddDTO.setTemplateId(HrConstants.TEMPLATE_ID_LIST);
        companyAdditionalFieldsAddDTOList.add(additionalFieldsAddDTO);

        List<CompanyAdditionalFieldsVO> companyAdditionalFieldsVOList = batchSave(companyAdditionalFieldsAddDTOList, tokenUser);
        // 返回当前修改VO
        return companyAdditionalFieldsVOList.parallelStream()
                .filter(companyAdditionalFieldsVO -> companyAdditionalFieldsVO.getCompanyId()
                        .equals(companyAdditionalFieldsAddDTO.getCompanyId())).findFirst().orElse(null);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public CompanyAdditionalFieldsVO saveForCustom(CompanyAdditionalFieldsAddDTO companyAdditionalFieldsAddDTO, TokenUser tokenUser) {
        //花名册添加员工字段时校验是否和公司下社保子项重复
        if (!StringUtils.isEmpty(companyAdditionalFieldsAddDTO.getCompanyId())) {
            if (socProgService.checkEmpItemName(companyAdditionalFieldsAddDTO.getCompanyId(), companyAdditionalFieldsAddDTO.getFieldName(), tokenUser)) {
                throw new ParamException("公司下社保子项存在相同的字段名");
            }
        }
        checkFieldsForSave(companyAdditionalFieldsAddDTO);
        // 校验自定义模板-默认模板中是否存在此字段
        String fieldName = companyAdditionalFieldsAddDTO.getFieldName();
        String moduleType = companyAdditionalFieldsAddDTO.getModuleType();
        checkSameName(moduleType, fieldName, tokenUser);
        // 转DO
        CompanyAdditionalFieldsDO companyAdditionalFieldsDO = companyAdditionalFieldsAddDTO.to(CompanyAdditionalFieldsDO.class);
        // 保存
        companyAdditionalFieldsDO = save(companyAdditionalFieldsDO, tokenUser.getSiteId(), tokenUser.getUserId());
        return companyAdditionalFieldsDO.to(CompanyAdditionalFieldsVO.class);
    }

    @Override
    public CompanyAdditionalFieldsVO saveForCustom2(CompanyAdditionalFieldsAddDTO companyAdditionalFieldsAddDTO, TokenUser tokenUser) {
        //花名册添加员工字段时校验是否和公司下社保子项重复
        if (!StringUtils.isEmpty(companyAdditionalFieldsAddDTO.getCompanyId())) {
            if (socProgService.checkEmpItemName(companyAdditionalFieldsAddDTO.getCompanyId(), companyAdditionalFieldsAddDTO.getFieldName(), tokenUser)) {
                throw new ParamException("公司下社保子项存在相同的字段名");
            }
        }
        checkFieldsForSave(companyAdditionalFieldsAddDTO);
        // 可选字段取用花名册 取消此检测
//        // 校验自定义模板-默认模板中是否存在此字段
//        String fieldName = companyAdditionalFieldsAddDTO.getFieldName();
//        String moduleType = companyAdditionalFieldsAddDTO.getModuleType();
//        checkSameName(moduleType, fieldName, tokenUser);
        // 转DO
        CompanyAdditionalFieldsDO companyAdditionalFieldsDO = companyAdditionalFieldsAddDTO.to(CompanyAdditionalFieldsDO.class);
        // 保存
        companyAdditionalFieldsDO = save(companyAdditionalFieldsDO, tokenUser.getSiteId(), tokenUser.getUserId());
        return companyAdditionalFieldsDO.to(CompanyAdditionalFieldsVO.class);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public CompanyAdditionalFieldsVO copyForCustom(CompanyAdditionalFieldsAddDTO companyAdditionalFieldsAddDTO, TokenUser tokenUser) {

        String fieldName = companyAdditionalFieldsAddDTO.getFieldName();
        String moduleType = companyAdditionalFieldsAddDTO.getModuleType();
        ParamException.hasText(moduleType, "moduleType不能为空");
        String companyId = companyAdditionalFieldsAddDTO.getCompanyId();
        Long sourceId = companyAdditionalFieldsAddDTO.getSourceId();
        ParamException.notNull(sourceId, "sourceId不能为空");
        // 是否存在同名字段
        boolean flag = false;
        // 查询同名字段
        List<CompanyAdditionalFieldsDO> companyAdditionalFieldsDOS = selectByModuleTypeAndFiledName(null, fieldName, companyId);
        for (CompanyAdditionalFieldsDO companyAdditionalFieldsDO : companyAdditionalFieldsDOS) {
            String templateId1 = companyAdditionalFieldsDO.getTemplateId();
            // 员工设置需要的数据： templateId1 == null
            if (templateId1 != null) {
                continue;
            }
            flag = true;
            // 更新,sourceId永远是开启的模板中的对应字段id
            //转DO
            CompanyAdditionalFieldsDO companyAdditionalFieldsDO1 = companyAdditionalFieldsAddDTO.to(CompanyAdditionalFieldsDO.class);
            companyAdditionalFieldsDO1.setId(companyAdditionalFieldsDO.getId());
            //根据主键更新，只更新非null值
            updateByIdSelective(companyAdditionalFieldsDO1, tokenUser.getSiteId(), tokenUser.getUserId());
            break;
        }
        if (flag) {
            return null;
        }
        // 转DO
        CompanyAdditionalFieldsDO companyAdditionalFieldsDO = companyAdditionalFieldsAddDTO.to(CompanyAdditionalFieldsDO.class);
        // 保存
        companyAdditionalFieldsDO = save(companyAdditionalFieldsDO, tokenUser.getSiteId(), tokenUser.getUserId());
        return companyAdditionalFieldsDO.to(CompanyAdditionalFieldsVO.class);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public List<CompanyAdditionalFieldsVO> listCopyForCustom(List<CompanyAdditionalFieldsDO> companyAdditionalFieldsDOS, TokenUser tokenUser) {
        List<CompanyAdditionalFieldsVO> list = new ArrayList<>();
        if (!CollectionUtils.isEmpty(companyAdditionalFieldsDOS)) {
            for (CompanyAdditionalFieldsDO additionalFieldsDO : companyAdditionalFieldsDOS) {
                CompanyAdditionalFieldsAddDTO fieldsAddDTO = additionalFieldsDO.to(CompanyAdditionalFieldsAddDTO.class);
                // 复制数据，新建，已存在同名的跳过
                fieldsAddDTO.setTemplateId(null);
                fieldsAddDTO.setSourceId(additionalFieldsDO.getId());

                CompanyAdditionalFieldsVO companyAdditionalFieldsVO = copyForCustom(fieldsAddDTO, tokenUser);
                if (companyAdditionalFieldsVO != null) {
                    list.add(companyAdditionalFieldsVO);
                }
            }
        }
        return list;
    }

    /**
     * 校验自定义模板-默认模板中是否存在此字段
     *
     * @param moduleCode 模块code
     * @param fieldName  字段名称
     * @param tokenUser  当前用户
     */
    private void checkSameName(String moduleCode, String fieldName, TokenUser tokenUser) {
        // 校验自定义模板-默认模板中是否存在此字段
        CustomTemplateFieldQuery query = new CustomTemplateFieldQuery();
        query.setModuleCode(moduleCode);
        List<CustomTemplateFieldListVO> customTemplateFieldListVOS = customTemplateFieldService.listDefaultField(query, tokenUser);
        for (CustomTemplateFieldListVO customTemplateFieldListVO : customTemplateFieldListVOS) {
            if (fieldName.equals(customTemplateFieldListVO.getFieldName())) {
                throw new ParamException("不允许使用与系统模板重复的字段名");
            }
        }
    }

    /**
     * 校验字段
     *
     * @param companyAdditionalFieldsAddDTO 公司员工额外字段表新建对象
     */
    private void checkFieldsForSave(CompanyAdditionalFieldsAddDTO companyAdditionalFieldsAddDTO) {
        //字段时长度必填
        if (companyAdditionalFieldsAddDTO.getFieldType().equals(FIELD_TYPE_TEXT)) {
            companyAdditionalFieldsAddDTO.setTextLength(10);
        }
        if (companyAdditionalFieldsAddDTO.getFieldType().equals(FIELD_TYPE_TEXTAREA)) {
            companyAdditionalFieldsAddDTO.setTextLength(50);
        }
        List<CompanyAdditionalFieldsDO> companyAdditionalFieldsDOList =
                selectByModuleAndFiledName(null
                        , companyAdditionalFieldsAddDTO.getFieldName(), companyAdditionalFieldsAddDTO.getCompanyId());
        if (!CollectionUtils.isEmpty(companyAdditionalFieldsDOList)) {
            for (CompanyAdditionalFieldsDO companyAdditionalFieldsDO : companyAdditionalFieldsDOList) {
                // list:列表 null:个人设置 具体id:模板
                String templateId = companyAdditionalFieldsAddDTO.getTemplateId();
                if (Objects.equals(templateId, companyAdditionalFieldsDO.getTemplateId())) {
                    // 自定义模板添加的
                    if (companyAdditionalFieldsAddDTO.getModuleType() != null) {
                        if (Objects.equals(companyAdditionalFieldsDO.getModuleType(), companyAdditionalFieldsAddDTO.getModuleType())) {
                            String company;
                            if (HrConstants.ADD_FIELD_COMPANY_SITE.equals(companyAdditionalFieldsAddDTO.getCompanyId())) {
                                company = "租户";
                            } else {
                                company = "用工单位";
                            }
                            throw new ParamException("当前" + company + "下存在相同的字段名【" + companyAdditionalFieldsAddDTO.getFieldName() + "】");
                        }
                    } else {
                        String company;
                        if (HrConstants.ADD_FIELD_COMPANY_SITE.equals(companyAdditionalFieldsAddDTO.getCompanyId())) {
                            company = "租户";
                        } else {
                            company = "用工单位";
                        }
                        throw new ParamException("当前" + company + "下存在相同的字段名【" + companyAdditionalFieldsAddDTO.getFieldName() + "】");
                    }
                }
            }
        }

        if (companyAdditionalFieldsAddDTO.getFieldType().equals(FIELD_TYPE_OPTION)) {
            if (companyAdditionalFieldsAddDTO.getOptions() == null) {
                throw new ParamException("选项为空时不能添加");
            }
            String[] dropDownArray;
            dropDownArray = companyAdditionalFieldsAddDTO.getOptions().split(",");
            List<String> list = Arrays.asList(dropDownArray);
            Set<String> set = new HashSet<>(list);
            if (list.size() != set.size()) {
                throw new ParamException("自定义选项不能重复");
            }
        }
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int update(CompanyAdditionalFieldsUpdateDTO companyAdditionalFieldsUpdateDTO, TokenUser tokenUser) {
        //花名册添加员工字段时校验是否和公司下社保子项重复
        if (!StringUtils.isEmpty(companyAdditionalFieldsUpdateDTO.getCompanyId())) {
            if (socProgService.checkEmpItemName(companyAdditionalFieldsUpdateDTO.getCompanyId(), companyAdditionalFieldsUpdateDTO.getFieldName(), tokenUser)) {
                throw new ParamException("公司下社保子项存在相同的字段名");
            }
        }
        //校验模板花名册中是否已存在该字段
        List<HeaderFieldsTemplateListVO> headerFieldsTemplateDOList = adminProviderService.selectHeaderByModuleAndName(EMP_INFO_BY_COMPANY, companyAdditionalFieldsUpdateDTO.getFieldName());
        ParamException.isTrue(CollectionUtils.isEmpty(headerFieldsTemplateDOList), "修改失败，字段已在花名册模板字段中使用！");
        String fieldName = companyAdditionalFieldsUpdateDTO.getFieldName();
        String companyId = companyAdditionalFieldsUpdateDTO.getCompanyId();
        // 判断是否需要修改该用工单位的合同模板
        if (StrKit.isNotEmpty(companyAdditionalFieldsUpdateDTO.getId())
                && StrKit.isNotEmpty(companyId)
                && StrKit.isNotEmpty(fieldName)) {
            // 查找字段名称，判断是否需要修改改用工单位的模板
            CompanyAdditionalFieldsDO companyAdditionalFieldsDO = this
                    .selectDOById(companyAdditionalFieldsUpdateDTO.getId(), tokenUser.getSiteId());
            ParamException.notNull(companyAdditionalFieldsDO, "根据id没有找到对应的数据，请刷新重试或联系管理员");
            if (!companyAdditionalFieldsDO.getFieldName().equals(fieldName)) {
                boolean isreplace = false;
                int desc = 0;
                String oldFieldName = companyAdditionalFieldsDO.getFieldName();
                if ("basic".equals(companyAdditionalFieldsDO.getModuleCode())) {
                    desc = 1;
                    isreplace = true;
                } else if ("contact".equals(companyAdditionalFieldsDO.getModuleCode())) {
                    desc = 2;
                    isreplace = true;
                }
                if (isreplace) {
                    // 修改合同模板
                    List<TemplateDO> templateDOList = contractProviderService
                            .selectByCompanyId(companyId, tokenUser.getSiteId());
                    for (TemplateDO templateDO : templateDOList) {
                        if (templateDO.getContent() == null || templateDO.getContentJson() == null) {
                            continue;
                        }
                        String newFieldDesc;
                        String oldFieldDesc;
                        String oldFieldNameDesc;
                        if (desc == 1) {
                            oldFieldDesc = oldFieldName + "(基本信息)";
                            newFieldDesc = fieldName + "(基本信息)";
                        } else {
                            oldFieldDesc = oldFieldName + "(联系信息)";
                            newFieldDesc = fieldName + "(联系信息)";
                        }
                        if (templateDO.getContent().contains("#" + oldFieldDesc + "#")) {
                            // 替换
                            if (desc == 1) {
                                oldFieldNameDesc = oldFieldName + "\\(基本信息\\)";
                            } else {
                                oldFieldNameDesc = oldFieldName + "\\(联系信息\\)";
                            }
                            templateDO.setContent(templateDO.getContent()
                                    .replaceAll("\\#" + oldFieldNameDesc + "\\#", "\\#" + newFieldDesc + "\\#"));
                            templateDO.setContentJson(templateDO.getContentJson()
                                    .replaceAll("\\#" + oldFieldNameDesc + "\\#", "\\#" + newFieldDesc + "\\#"));
                            contractProviderService.updataTemplateDO(templateDO, tokenUser);
                        }
                    }
                }
            }
        }
        // 查询该字段是否在已开启的模板下
        CustomTemplateVO customTemplateVO = customTemplateService.selectOpenTemplate(companyAdditionalFieldsUpdateDTO.getModuleType(),
                companyAdditionalFieldsUpdateDTO.getCompanyId(), tokenUser);
        if (customTemplateVO != null) {
            List<CompanyAdditionalFieldsListVO> additionalFieldsListVOS = customTemplateVO.getAdditionalFieldsListVOS();
            if (!CollectionUtils.isEmpty(additionalFieldsListVOS)) {
                CompanyAdditionalFieldsVO companyAdditionalFieldsVO = selectById(companyAdditionalFieldsUpdateDTO.getId(), tokenUser.getSiteId());
                for (CompanyAdditionalFieldsListVO additionalFieldsListVO : additionalFieldsListVOS) {
                    if (Objects.equals(companyAdditionalFieldsVO.getId(), additionalFieldsListVO.getId())) {
                        throw new ParamException("【" + companyAdditionalFieldsUpdateDTO.getFieldName() + "】已存在于已启用的模板" +
                                "【" + customTemplateVO.getName() + "】中，不允许修改");
                    }
                }
            }
        }

        checkFieldsForUpdate(companyAdditionalFieldsUpdateDTO, tokenUser);
        List<CompanyNecessaryFieldDO> companyNecessaryFieldDOList =
                companyNecessaryFieldService.selectByModuleAndFiledName(companyAdditionalFieldsUpdateDTO.getModuleCode()
                        , companyAdditionalFieldsUpdateDTO.getFieldName(), companyAdditionalFieldsUpdateDTO.getCompanyId());
        if (!CollectionUtils.isEmpty(companyNecessaryFieldDOList)) {
            throw new ParamException("当前模块下存在相同的字段名");
        }
        //转DO
        CompanyAdditionalFieldsDO companyAdditionalFieldsDO = companyAdditionalFieldsUpdateDTO.to(CompanyAdditionalFieldsDO.class);
        //根据主键更新，只更新非null值
        return updateByIdSelective(companyAdditionalFieldsDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int update2(CompanyAdditionalFieldsUpdateDTO companyAdditionalFieldsUpdateDTO, TokenUser tokenUser) {

        ParamException.isTrue(org.apache.commons.lang3.StringUtils.isNotBlank(companyAdditionalFieldsUpdateDTO.getFieldName())
                , "字段名称不能为空或纯空格");
        companyAdditionalFieldsUpdateDTO.setFieldName(companyAdditionalFieldsUpdateDTO.getFieldName().trim());
        // 编辑字段校验
        checkFieldsForUpdate2(companyAdditionalFieldsUpdateDTO, tokenUser);
        //花名册添加员工字段时校验是否和公司下社保子项重复
        if (!StringUtils.isEmpty(companyAdditionalFieldsUpdateDTO.getCompanyId())) {
            if (socProgService.checkEmpItemName(companyAdditionalFieldsUpdateDTO.getCompanyId()
                    , companyAdditionalFieldsUpdateDTO.getFieldName(), tokenUser)) {
                throw new ParamException("公司下社保子项存在相同的字段名");
            }
        }
        Long updateId = companyAdditionalFieldsUpdateDTO.getId();
        String newName = companyAdditionalFieldsUpdateDTO.getFieldName();
        String companyId = companyAdditionalFieldsUpdateDTO.getCompanyId();
        // 查找字段名称，判断是否需要修改改用工单位的模板
        CompanyAdditionalFieldsDO oldDO = this.selectDOById(updateId, tokenUser.getSiteId());
        ParamException.notNull(oldDO, "根据id没有找到对应的数据，请刷新重试或联系管理员");
        if (!newName.equals(oldDO.getFieldName())) {
            List<CompanyNecessaryFieldDO> companyNecessaryFieldDOList = companyNecessaryFieldService
                    .selectByModuleAndFiledName(null, newName, companyId);
            if (!CollectionUtils.isEmpty(companyNecessaryFieldDOList)) {
                throw new ParamException("修改后名称与花名册字段相同");
            }
            List<CompanyAdditionalFieldsDO> newNameList = selectByModuleAndFiledName(null, newName, companyId);
            newNameList = newNameList.parallelStream().filter(companyAdditionalFieldsDO -> !companyAdditionalFieldsUpdateDTO
                    .getId().equals(companyAdditionalFieldsDO.getId())).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(newNameList)) {
                throw new ParamException("修改后名称已存在自定义字段中");
            }
        }
        // 检查租户下模板中的字段(按名称查找所有code)
        List<CompanyAdditionalFieldsDO> companyAdditionalFieldsDOList = selectByModuleAndFiledNameInSite(
                null, oldDO.getFieldName(), tokenUser.getSiteId());
        for (CompanyAdditionalFieldsDO companyAdditionalFieldsDO : companyAdditionalFieldsDOList) {
            // 修改模板中字段信息
            CompanyAdditionalFieldsDO updateDO = companyAdditionalFieldsUpdateDTO.to(CompanyAdditionalFieldsDO.class);
            updateDO.setId(companyAdditionalFieldsDO.getId());
            updateDO.setCompanyId(companyAdditionalFieldsDO.getCompanyId());
            updateDO.setModuleCode(companyAdditionalFieldsDO.getModuleCode());
            updateDO.setModuleType(companyAdditionalFieldsDO.getModuleType());
            updateDO.setSort(companyAdditionalFieldsDO.getSort());
            updateDO.setIsEdit(companyAdditionalFieldsDO.getIsEdit());
            updateDO.setTemplateId(companyAdditionalFieldsDO.getTemplateId());
            updateDO.setSourceId(companyAdditionalFieldsDO.getSourceId());
            updateByIdSelective(updateDO, tokenUser.getSiteId(), tokenUser.getUserId());
        }
        // 租户预登记模板中也修改
        List<CompanyAdditionalFieldsListVO> siteAdditionalFieldsListVOList
                = listByCompanyId("checkIn", "site", HrConstants.TEMPLATE_ID_LIST, tokenUser);
        for (CompanyAdditionalFieldsListVO additionalFieldsListVO : siteAdditionalFieldsListVOList) {
            // 字段名称相同 且模块也一样 视为同一字段
            if (oldDO.getFieldName().equals(additionalFieldsListVO.getFieldName())
                    && oldDO.getModuleCode().equals(additionalFieldsListVO.getModuleCode())) {
                CompanyAdditionalFieldsDO updateDO = companyAdditionalFieldsUpdateDTO.to(CompanyAdditionalFieldsDO.class);
                updateDO.setId(additionalFieldsListVO.getId());
                updateDO.setCompanyId("site");
                updateDO.setModuleType("checkIn");
                updateDO.setTemplateId(HrConstants.TEMPLATE_ID_LIST);
                updateDO.setSourceId(null);
                updateByIdSelective(updateDO, tokenUser.getSiteId(), tokenUser.getUserId());
                break;
            }
        }
        return companyAdditionalFieldsDOList.size() + 1;
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int openField(Long companyAdditionalFieldsId, Boolean isOpen, TokenUser tokenUser) {
        CompanyAdditionalFieldsDO companyAdditionalFieldsDO = new CompanyAdditionalFieldsDO();
        companyAdditionalFieldsDO.setId(companyAdditionalFieldsId);
        companyAdditionalFieldsDO.setIsOpen(isOpen);
        return updateByIdSelective(companyAdditionalFieldsDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    @Override
    public int necessaryField(Long companyAdditionalFieldsId, Boolean isNecessary, TokenUser tokenUser) {
        CompanyAdditionalFieldsDO companyAdditionalFieldsDO = new CompanyAdditionalFieldsDO();
        companyAdditionalFieldsDO.setId(companyAdditionalFieldsId);
        companyAdditionalFieldsDO.setIsNecessary(isNecessary);
        return updateByIdSelective(companyAdditionalFieldsDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }


    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int updateForCustom(CompanyAdditionalFieldsUpdateDTO companyAdditionalFieldsUpdateDTO, TokenUser tokenUser) {
        // 原先的字段
        CompanyAdditionalFieldsVO companyAdditionalFieldsVO = selectById(companyAdditionalFieldsUpdateDTO.getId(), tokenUser.getSiteId());
        // 校验
        checkFieldsForUpdate(companyAdditionalFieldsUpdateDTO, tokenUser);
        String fieldName = companyAdditionalFieldsUpdateDTO.getFieldName();
        String moduleType = companyAdditionalFieldsUpdateDTO.getModuleType();
        // 校验自定义模板-默认模板中是否存在此字段
        checkSameName(moduleType, fieldName, tokenUser);
        // 字段修改后，若存在于已启用模版下，员工设置字段跟随改变；
        CustomTemplateVO customTemplateVO = customTemplateService.selectOpenTemplate(companyAdditionalFieldsUpdateDTO.getModuleType(),
                companyAdditionalFieldsUpdateDTO.getCompanyId(), tokenUser);
        if (customTemplateVO != null) {
            // 开启的模板里的自定义字段
            List<CompanyAdditionalFieldsListVO> additionalFieldsListVOS = customTemplateVO.getAdditionalFieldsListVOS();
            if (!CollectionUtils.isEmpty(additionalFieldsListVOS)) {
                for (CompanyAdditionalFieldsListVO additionalFieldsListVO : additionalFieldsListVOS) {
                    if (companyAdditionalFieldsVO.getFieldName().equals(additionalFieldsListVO.getFieldName())) {
                        // 开启的模板里的自定义字段对应的templateId=null的字段
                        CompanyAdditionalFieldsDO companyAdditionalFieldsDO
                                = listBySourceId(companyAdditionalFieldsVO.getSourceId(),
                                companyAdditionalFieldsVO.getFieldName(), tokenUser);
                        companyAdditionalFieldsDO.setFieldName(companyAdditionalFieldsUpdateDTO.getFieldName());
                        companyAdditionalFieldsDO.setDescription(companyAdditionalFieldsUpdateDTO.getDescription());

                        //根据主键更新，只更新非null值
                        updateByIdSelective(companyAdditionalFieldsDO, tokenUser.getSiteId(), tokenUser.getUserId());
                        break;
                    }
                }
            }
        }
        //转DO
        CompanyAdditionalFieldsDO companyAdditionalFieldsDO = companyAdditionalFieldsUpdateDTO.to(CompanyAdditionalFieldsDO.class);
        //根据主键更新，只更新非null值
        return updateByIdSelective(companyAdditionalFieldsDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    /**
     * 编辑字段时校验
     *
     * @param companyAdditionalFieldsUpdateDTO 自定义字段修改对象
     * @param tokenUser                        当前用户
     */
    private void checkFieldsForUpdate(CompanyAdditionalFieldsUpdateDTO companyAdditionalFieldsUpdateDTO, TokenUser tokenUser) {
        CompanyAdditionalFieldsDO companyAdditionalFields = selectDOById(
                companyAdditionalFieldsUpdateDTO.getId(), tokenUser.getSiteId());
        if (companyAdditionalFields == null) {
            throw new ParamException("未查到，请重试");
        }
        if (!companyAdditionalFields.getFieldType().equals(companyAdditionalFieldsUpdateDTO.getFieldType())) {
            throw new ParamException("不允许修改字段类型，请重试");
        }
        if (companyAdditionalFieldsUpdateDTO.getIsOpen() != null && companyAdditionalFieldsUpdateDTO.getIsNecessary() != null
                && companyAdditionalFieldsUpdateDTO.getIsEdit() != null) {
            //从open的开启到关闭
            if (companyAdditionalFields.getIsOpen() && !companyAdditionalFieldsUpdateDTO.getIsOpen()) {
                companyAdditionalFieldsUpdateDTO.setIsNecessary(false);
            }
            //从open的关闭 到修改或者必填的开启
            Boolean flag = !companyAdditionalFields.getIsOpen() &&
                    (companyAdditionalFieldsUpdateDTO.getIsNecessary() || companyAdditionalFieldsUpdateDTO.getIsEdit() == 1);
            if (flag) {
                companyAdditionalFieldsUpdateDTO.setIsOpen(true);
            }
        }
        List<CompanyAdditionalFieldsDO> companyAdditionalFieldsDOList =
                selectByModuleAndFiledName(null
                        , companyAdditionalFieldsUpdateDTO.getFieldName(), companyAdditionalFields.getCompanyId());
        if (!CollectionUtils.isEmpty(companyAdditionalFieldsDOList)) {
            companyAdditionalFieldsDOList = companyAdditionalFieldsDOList.stream()
                    .filter(s -> s.getTemplateId() == null)
                    .collect(Collectors.toList());
            for (CompanyAdditionalFieldsDO companyAdditionalFieldsDO : companyAdditionalFieldsDOList) {
                if (companyAdditionalFields.getId().equals(companyAdditionalFieldsDO.getId())) {
                    continue;
                }
                // 自定义模板添加的
                if (companyAdditionalFieldsUpdateDTO.getModuleType() != null) {
                    if (Objects.equals(companyAdditionalFieldsDO.getModuleType(), companyAdditionalFieldsUpdateDTO.getModuleType())) {
                        String company;
                        if (HrConstants.ADD_FIELD_COMPANY_SITE.equals(companyAdditionalFieldsUpdateDTO.getCompanyId())) {
                            company = "租户";
                        } else {
                            company = "用工单位";
                        }
                        throw new ParamException("当前" + company + "下存在相同的字段名【" + companyAdditionalFieldsUpdateDTO.getFieldName() + "】");
                    }
                } else {
                    String company;
                    if (HrConstants.ADD_FIELD_COMPANY_SITE.equals(companyAdditionalFieldsUpdateDTO.getCompanyId())) {
                        company = "租户";
                    } else {
                        company = "用工单位";
                    }
                    throw new ParamException("当前" + company + "下存在相同的字段名【" + companyAdditionalFieldsUpdateDTO.getFieldName() + "】");
                }
            }
        }

        if (companyAdditionalFieldsUpdateDTO.getFieldType().equals(FIELD_TYPE_OPTION)) {
            if (companyAdditionalFieldsUpdateDTO.getOptions() == null) {
                throw new ParamException("选项为空时不能添加");
            }
            String[] dropDownArray;
            dropDownArray = companyAdditionalFieldsUpdateDTO.getOptions().split(",");
            List<String> list = Arrays.asList(dropDownArray);
            Set<String> set = new HashSet<>(list);
            if (list.size() != set.size()) {
                throw new ParamException("自定义选项不能重复");
            }
        }
    }

    /**
     * 编辑字段时校验
     *
     * @param companyAdditionalFieldsUpdateDTO 自定义字段修改对象
     * @param tokenUser                        当前用户
     */
    private void checkFieldsForUpdate2(CompanyAdditionalFieldsUpdateDTO companyAdditionalFieldsUpdateDTO, TokenUser tokenUser) {
        Long updateId = companyAdditionalFieldsUpdateDTO.getId();
        String fieldName = companyAdditionalFieldsUpdateDTO.getFieldName();
        String companyId = companyAdditionalFieldsUpdateDTO.getCompanyId();
        ParamException.notNull(updateId, "字段id不能为空");
        ParamException.notNull(fieldName, "字段名称不能为空");
        ParamException.notNull(companyId, "用工单位id不能为空");
        CompanyAdditionalFieldsDO oldDO = selectDOById(updateId, tokenUser.getSiteId());
        ParamException.notNull(oldDO, "未查到，请重试");
        ParamException.isTrue(oldDO.getCompanyId().equals(companyId), "用工单位不能发生变化");
        ParamException.isTrue(oldDO.getFieldType().equals(companyAdditionalFieldsUpdateDTO.getFieldType())
                , "不允许修改字段类型，请重试");
        if (companyAdditionalFieldsUpdateDTO.getIsOpen() != null && companyAdditionalFieldsUpdateDTO.getIsNecessary() != null
                && companyAdditionalFieldsUpdateDTO.getIsEdit() != null) {
            //从open的开启到关闭
            if (oldDO.getIsOpen() && !companyAdditionalFieldsUpdateDTO.getIsOpen()) {
                companyAdditionalFieldsUpdateDTO.setIsNecessary(false);
            }
            //从open的关闭 到修改或者必填的开启
            boolean flag = !oldDO.getIsOpen() &&
                    (companyAdditionalFieldsUpdateDTO.getIsNecessary() || companyAdditionalFieldsUpdateDTO.getIsEdit() == 1);
            if (flag) {
                companyAdditionalFieldsUpdateDTO.setIsOpen(true);
            }
        }
        if (companyAdditionalFieldsUpdateDTO.getFieldType().equals(FIELD_TYPE_OPTION)) {
            ParamException.notNull(companyAdditionalFieldsUpdateDTO.getOptions(), "选项为空时不能添加");
            String[] dropDownArray;
            dropDownArray = companyAdditionalFieldsUpdateDTO.getOptions().split(",");
            List<String> list = Arrays.asList(dropDownArray);
            Set<String> set = new HashSet<>(list);
            ParamException.isTrue(list.size() == set.size(), "自定义选项不能重复");
        }
        // 表头中是否含有该字段
        List<HeaderFieldsTemplateListVO> headerFieldsTemplateDOList = adminProviderService
                .selectHeaderByModuleAndName(EMP_INFO_BY_COMPANY, fieldName);
        ParamException.isTrue(CollectionUtils.isEmpty(headerFieldsTemplateDOList), "修改失败，字段已在花名册模板字段中使用！");
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteByIds(TokenUser tokenUser, Long... companyAdditionalFieldsIds) {
        return logicalDeleteByIds(tokenUser.getSiteId(), tokenUser.getUserId(), (Object[]) companyAdditionalFieldsIds);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteByTemplateIdList(List<String> templateIdList, TokenUser tokenUser) {
        List<CompanyAdditionalFieldsDO> companyAdditionalFieldsDOS = listByTemplateIdList(templateIdList, tokenUser);
        // 循环删除
        int count = 0;
        if (!CollectionUtils.isEmpty(companyAdditionalFieldsDOS)) {
            for (CompanyAdditionalFieldsDO companyAdditionalFieldsDO : companyAdditionalFieldsDOS) {
                TokenUser tokenUser1 = new TokenUser();
                tokenUser1.setSiteId(companyAdditionalFieldsDO.getSiteId());
                tokenUser1.setUserId(tokenUser.getUserId());
                count += deleteByIds(tokenUser1, companyAdditionalFieldsDO.getId());
            }
        }
        return count;
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteForPc(TokenUser tokenUser, Long companyAdditionalFieldsId) {

        CompanyAdditionalFieldsVO companyAdditionalFieldsVO = selectById(companyAdditionalFieldsId, tokenUser.getSiteId());
        // 查询该字段是否在已开启的模板下
        CustomTemplateVO customTemplateVO = customTemplateService.selectOpenTemplate(companyAdditionalFieldsVO.getModuleType(),
                companyAdditionalFieldsVO.getCompanyId(), tokenUser);
        if (customTemplateVO != null) {
            List<CompanyAdditionalFieldsListVO> additionalFieldsListVOS = customTemplateVO.getAdditionalFieldsListVOS();
            if (!CollectionUtils.isEmpty(additionalFieldsListVOS)) {
                for (CompanyAdditionalFieldsListVO additionalFieldsListVO : additionalFieldsListVOS) {
                    if (Objects.equals(companyAdditionalFieldsVO.getId(), additionalFieldsListVO.getId())) {
                        throw new ParamException("【" + companyAdditionalFieldsVO.getFieldName() + "】已存在于已启用的模板" +
                                "【" + customTemplateVO.getName() + "】中，不允许删除");
                    }
                }
            }
        }

        List<EmpAdditionalFieldsDO> empAdditionalFieldsDOList =
                empAdditionalFieldsService.selectByFiledId(companyAdditionalFieldsId);
        //循环删除员工的输入的信息
        if (!CollectionUtils.isEmpty(empAdditionalFieldsDOList)) {
            for (EmpAdditionalFieldsDO empAdditionalFieldsDO : empAdditionalFieldsDOList) {
                TokenUser tokenUser1 = new TokenUser();
                tokenUser1.setSiteId(empAdditionalFieldsDO.getSiteId());
                tokenUser1.setUserId(tokenUser.getUserId());
                empAdditionalFieldsService.deleteByIds(tokenUser1, empAdditionalFieldsDO.getId());
            }
        }
        return logicalDeleteByIds(tokenUser.getSiteId(), tokenUser.getUserId(), companyAdditionalFieldsId);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteForPc2(TokenUser tokenUser, Long companyAdditionalFieldsId) {
        CompanyAdditionalFieldsDO oldDO = selectDOById(companyAdditionalFieldsId, tokenUser.getSiteId());
        if (oldDO == null) {
            return 1;
        }
        String fieldName = oldDO.getFieldName();
        // 检查租户下模板中的字段(按名称查找所有code)
        List<CompanyAdditionalFieldsDO> companyAdditionalFieldsDOList = selectByModuleAndFiledNameInSite(
                null, fieldName, tokenUser.getSiteId());
        deleteByIds(tokenUser, companyAdditionalFieldsDOList.parallelStream().map(BaseDO::getId).toArray(Long[]::new));
        // 租户预登记模板中也删除
        List<CompanyAdditionalFieldsListVO> siteAdditionalFieldsListVOList
                = listByCompanyId("checkIn", "site", HrConstants.TEMPLATE_ID_LIST, tokenUser);
        for (CompanyAdditionalFieldsListVO additionalFieldsListVO : siteAdditionalFieldsListVOList) {
            // 字段名称相同 且模块也一样 视为同一字段
            if (oldDO.getFieldName().equals(additionalFieldsListVO.getFieldName())
                    && oldDO.getModuleCode().equals(additionalFieldsListVO.getModuleCode())) {
                deleteByIds(tokenUser, additionalFieldsListVO.getId());
                break;
            }
        }

        // 删除员工的输入的信息
        List<EmpAdditionalFieldsDO> empAdditionalFieldsDOList = empAdditionalFieldsService.selectByFiledIds(
                companyAdditionalFieldsDOList.parallelStream().map(BaseDO::getId).collect(Collectors.toList()));
        if (!CollectionUtils.isEmpty(empAdditionalFieldsDOList)) {
            for (EmpAdditionalFieldsDO empAdditionalFieldsDO : empAdditionalFieldsDOList) {
                TokenUser tokenUser1 = new TokenUser();
                tokenUser1.setSiteId(empAdditionalFieldsDO.getSiteId());
                tokenUser1.setUserId(tokenUser.getUserId());
                empAdditionalFieldsService.deleteByIds(tokenUser1, empAdditionalFieldsDO.getId());
            }
        }
        return logicalDeleteByIds(tokenUser.getSiteId(), tokenUser.getUserId(), companyAdditionalFieldsId);
    }


    @Override
    public CompanyAdditionalFieldsVO selectById(Long companyAdditionalFieldsId, String siteId) {
        CompanyAdditionalFieldsDO companyAdditionalFieldsDO = selectDOById(companyAdditionalFieldsId, siteId);
        if (companyAdditionalFieldsDO == null) {
            return null;
        }
        return companyAdditionalFieldsDO.to(CompanyAdditionalFieldsVO.class);
    }

    @Override
    public CompanyAdditionalFieldsDO selectByIdNoSite(Long companyAdditionalFieldsId) {
        Example example = new Example(CompanyAdditionalFieldsDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("id", companyAdditionalFieldsId);
        return companyAdditionalFieldsDAO.selectOneByExample(example);
    }

    @Override
    public List<CompanyAdditionalFieldsDO> selectByModuleAndFiledName(String module, String filedName, String companyId) {
        Example example = new Example(CompanyAdditionalFieldsDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("fieldName", filedName)
                .andEqualTo("companyId", companyId);
        if (module != null) {
            example.and().andEqualTo("moduleCode", module);
        }
        return companyAdditionalFieldsDAO.selectByExample(example);
    }

    @Override
    public List<CompanyAdditionalFieldsDO> selectByModuleAndFiledNameInSite(String module, String filedName, String siteId) {
        Example example = new Example(CompanyAdditionalFieldsDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("fieldName", filedName)
                .andEqualTo("siteId", siteId);
        if (module != null) {
            example.and().andEqualTo("moduleCode", module);
        }
        return companyAdditionalFieldsDAO.selectByExample(example);
    }

    @Override
    public List<CompanyAdditionalFieldsDO> selectByModuleTypeAndFiledName(String moduleType, String filedName, String companyId) {
        Example example = new Example(CompanyAdditionalFieldsDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("fieldName", filedName)
                .andEqualTo("companyId", companyId);
        if (moduleType != null) {
            example.and().andEqualTo("moduleType", moduleType);
        }
        return companyAdditionalFieldsDAO.selectByExample(example);
    }

    @Override
    public List<CompanyAdditionalFieldsListVO> select(CompanyAdditionalFieldsQuery companyAdditionalFieldsQuery, String siteId) {
        List<CompanyAdditionalFieldsDO> companyAdditionalFieldsDOList = selectDO(companyAdditionalFieldsQuery, siteId);
        if (CollectionUtils.isEmpty(companyAdditionalFieldsDOList)) {
            return companyAdditionalFieldsDOList == null ? null : new ArrayList<>();
        }
        return companyAdditionalFieldsDOList.stream()
                .filter(companyAdditionalFieldsDO -> companyAdditionalFieldsDO.getTemplateId() == null)
                .map(companyAdditionalFieldsDO -> {
                    CompanyAdditionalFieldsListVO companyAdditionalFieldsVO =
                            companyAdditionalFieldsDO.to(CompanyAdditionalFieldsListVO.class);
                    if (companyAdditionalFieldsVO.getFieldType() != null && companyAdditionalFieldsVO.getFieldType() == 1) {
                        String[] dropDownArray;
                        dropDownArray = companyAdditionalFieldsVO.getOptions().split(",");
                        companyAdditionalFieldsVO.setDropDownArray(dropDownArray);
                    }
                    return companyAdditionalFieldsVO;
                })
                .collect(Collectors.toList());
    }

    @Override
    public int selectCount(CompanyAdditionalFieldsQuery companyAdditionalFieldsQuery, String siteId) {
        Example example = buildExample(companyAdditionalFieldsQuery, siteId);
        return companyAdditionalFieldsDAO.selectCountByExample(example);
    }

    @Override
    public Page<CompanyAdditionalFieldsListVO> selectPage(CompanyAdditionalFieldsQuery companyAdditionalFieldsQuery, String siteId) {
        Example example = buildExample(companyAdditionalFieldsQuery, siteId);
        Page<CompanyAdditionalFieldsDO> page = companyAdditionalFieldsDAO.selectPageByExample(example,
                companyAdditionalFieldsQuery.getPageNo(),
                companyAdditionalFieldsQuery.getPageSize());

        return page.to(CompanyAdditionalFieldsListVO.class);
    }

    @Override
    public CompanyAdditionalFieldsDO selectDOById(Long companyAdditionalFieldsId, String siteId) {
        return listById(companyAdditionalFieldsId, siteId);
    }

    @Override
    public List<CompanyAdditionalFieldsDO> selectByIdList(List<Long> companyAdditionalFieldsIdList, TokenUser tokenUser) {
        if (CollectionUtils.isEmpty(companyAdditionalFieldsIdList)) {
            return new ArrayList<>();
        }
        Example example = new Example(CompanyAdditionalFieldsDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", tokenUser.getSiteId())
                .andIn("id", companyAdditionalFieldsIdList);
        example.orderBy("sort");
        return companyAdditionalFieldsDAO.selectByExample(example);
    }

    @Override
    public List<CompanyAdditionalFieldsDO> selectDOByIds(List<Long> companyAdditionalFieldsIds, String siteId) {
        if (CollectionUtils.isEmpty(companyAdditionalFieldsIds)) {
            return new ArrayList<>();
        }
        Example example = new Example(CompanyAdditionalFieldsDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId)
                .andEqualTo("isOpen", true)
                .andIn("id", companyAdditionalFieldsIds);
        example.orderBy("sort");
        return companyAdditionalFieldsDAO.selectByExample(example);
    }

    @Override
    public List<CompanyAdditionalFieldsDO> selectDO(CompanyAdditionalFieldsQuery companyAdditionalFieldsQuery, String siteId) {
        Example example = buildExample(companyAdditionalFieldsQuery, siteId);
        return companyAdditionalFieldsDAO.selectByExample(example);
    }

    @Override
    public List<CompanyAdditionalFieldsListVO> selectOpenByCompanyId(String companyId, String siteId) {
        Example example = new Example(CompanyAdditionalFieldsDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("companyId", companyId)
                .andEqualTo("isOpen", true)
                .andIsNull("templateId")
                .andEqualTo("siteId", siteId);
        List<CompanyAdditionalFieldsDO> companyAdditionalFieldsDOList = companyAdditionalFieldsDAO.selectByExample(example);
        return companyAdditionalFieldsDOList.stream()
                .map(companyAdditionalFieldsDO -> {
                    CompanyAdditionalFieldsListVO companyAdditionalFieldsVO =
                            companyAdditionalFieldsDO.to(CompanyAdditionalFieldsListVO.class);
                    if (companyAdditionalFieldsVO.getFieldType() != null && companyAdditionalFieldsVO.getFieldType() == 1) {
                        String[] dropDownArray;
                        dropDownArray = companyAdditionalFieldsVO.getOptions().split(",");
                        companyAdditionalFieldsVO.setDropDownArray(dropDownArray);
                    }
                    return companyAdditionalFieldsVO;
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<CompanyAdditionalFieldsDO> selectOpenDoByCompanyId(String companyId, String siteId) {
        Example example = new Example(CompanyAdditionalFieldsDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("companyId", companyId)
                .andEqualTo("isOpen", true)
                .andEqualTo("siteId", siteId);
        return companyAdditionalFieldsDAO.selectByExample(example);
    }

    @Override
    public List<CompanyAdditionalFieldsListVO> selectByCompanyId(String companyId, String siteId) {
        Example example = new Example(CompanyAdditionalFieldsDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("companyId", companyId)
                .andIsNull("templateId")
                .andEqualTo("siteId", siteId);
        List<CompanyAdditionalFieldsDO> companyAdditionalFieldsDOList = companyAdditionalFieldsDAO.selectByExample(example);
        return companyAdditionalFieldsDOList.stream()
                .map(companyAdditionalFieldsDO -> {
                    CompanyAdditionalFieldsListVO companyAdditionalFieldsVO =
                            companyAdditionalFieldsDO.to(CompanyAdditionalFieldsListVO.class);
                    if (companyAdditionalFieldsVO.getFieldType() != null && companyAdditionalFieldsVO.getFieldType() == 1) {
                        String[] dropDownArray;
                        dropDownArray = companyAdditionalFieldsVO.getOptions().split(",");
                        companyAdditionalFieldsVO.setDropDownArray(dropDownArray);
                    }
                    return companyAdditionalFieldsVO;
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<CompanyAdditionalFieldsListVO> selectByCompanyId2(String companyId, String fieldName, String siteId) {
        List<String> moduleCodeList = EmpFieldModuleCodeKit.getAllModuleCodeList();
        Example example = new Example(CompanyAdditionalFieldsDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andIsNull("templateId")
                .andEqualTo("siteId", siteId)
                .andIn("moduleCode", moduleCodeList)
                .andEqualTo("companyId", companyId);
        if (org.apache.commons.lang3.StringUtils.isNotBlank(fieldName)) {
            example.and().andLike("fieldName", "%" + fieldName + "%");
        }
        List<CompanyAdditionalFieldsDO> companyAdditionalFieldsDOList = companyAdditionalFieldsDAO.selectByExample(example);
        return companyAdditionalFieldsDOList.parallelStream().map(companyAdditionalFieldsDO -> {
            CompanyAdditionalFieldsListVO companyAdditionalFieldsVO =
                    companyAdditionalFieldsDO.to(CompanyAdditionalFieldsListVO.class);
            // 下拉框放入选项
            if (companyAdditionalFieldsVO.getFieldType() != null && companyAdditionalFieldsVO.getFieldType() == 1) {
                String[] dropDownArray;
                dropDownArray = companyAdditionalFieldsVO.getOptions().split(",");
                companyAdditionalFieldsVO.setDropDownArray(dropDownArray);
            }
            return companyAdditionalFieldsVO;
        }).parallel().collect(Collectors.toList());
    }

    @Override
    public List<CompanyAdditionalFieldsDO> getByCompanyId(List<String> companyIdList, String fieldName, String siteId) {
        Example example = new Example(CompanyAdditionalFieldsDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId)
                .andEqualTo("fieldName", fieldName)
                .andIn("companyId", companyIdList);
        return companyAdditionalFieldsDAO.selectByExample(example);
    }

    @Override
    public List<CompanyAdditionalFieldsListVO> selectByCompanyId3(String companyId, String fieldName, String siteId) {
        List<String> moduleCodeList = EmpFieldModuleCodeKit.getAllModuleCodeList();
        Example example = new Example(CompanyAdditionalFieldsDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId)
                .andIn("moduleCode", moduleCodeList);
        if (org.apache.commons.lang3.StringUtils.isNotBlank(fieldName)) {
            example.and().andLike("fieldName", "%" + fieldName + "%");
        }
        if (!"site".equals(companyId)) {
            // 租户级别-模板左侧接口 查询所有用工单位自定义字段
            example.and()
                    .andEqualTo("companyId", companyId)
                    .andIsNull("templateId");
        } else {
            example.and()
                    .orEqualTo("templateId", "list")
                    .orIsNull("templateId");
        }
        List<CompanyAdditionalFieldsDO> companyAdditionalFieldsDOList = companyAdditionalFieldsDAO.selectByExample(example);
        if ("site".equals(companyId)) {
            List<CompanyAdditionalFieldsDO> companyAdditionalFieldsList = new ArrayList<>();
            // 租户级别-模板左侧接口 所有用工单位自定义字段按名称和模块去重
            Map<String, List<CompanyAdditionalFieldsDO>> moduleCodeListMap = companyAdditionalFieldsDOList.parallelStream()
                    .collect(Collectors.groupingBy(CompanyAdditionalFieldsDO::getModuleCode));
            for (String moduleCode : moduleCodeListMap.keySet()) {
                // 先按照创建时间排序
                List<CompanyAdditionalFieldsDO> companyAdditionalFieldList = moduleCodeListMap.get(moduleCode);
                companyAdditionalFieldList = companyAdditionalFieldList.parallelStream()
                        .sorted(Comparator.comparing(BaseCreateDO::getGmtCreate)).collect(Collectors.toList());
                // 再按照字段名称去重
                companyAdditionalFieldList = companyAdditionalFieldList.parallelStream()
                        .filter(distinctByKey(CompanyAdditionalFieldsDO::getFieldName)).collect(Collectors.toList());
                companyAdditionalFieldsList.addAll(companyAdditionalFieldList);
            }
            companyAdditionalFieldsDOList = companyAdditionalFieldsList;
        }
        return companyAdditionalFieldsDOList.parallelStream().map(companyAdditionalFieldsDO -> {
            CompanyAdditionalFieldsListVO companyAdditionalFieldsVO =
                    companyAdditionalFieldsDO.to(CompanyAdditionalFieldsListVO.class);
            // 下拉框放入选项
            if (companyAdditionalFieldsVO.getFieldType() != null && companyAdditionalFieldsVO.getFieldType() == 1) {
                String[] dropDownArray;
                dropDownArray = companyAdditionalFieldsVO.getOptions().split(",");
                companyAdditionalFieldsVO.setDropDownArray(dropDownArray);
            }
            return companyAdditionalFieldsVO;
        }).parallel().collect(Collectors.toList());
    }

    @Override
    public List<CompanyAdditionalFieldsListVO> selectByCompanyId4(String companyId, String fieldName, String siteId) {
        List<String> moduleCodeList = EmpFieldModuleCodeKit.getAllModuleCodeList();
        Example example = new Example(CompanyAdditionalFieldsDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andIsNull("templateId")
                .andEqualTo("siteId", siteId)
                .andIn("moduleCode", moduleCodeList);

        if (org.apache.commons.lang3.StringUtils.isNotBlank(fieldName)) {
            example.and().andLike("fieldName", "%" + fieldName + "%");
        }
        if (!"site".equals(companyId)) {
            // 租户级别-模板左侧接口 查询所有用工单位自定义字段
            example.and().andEqualTo("companyId", companyId);
        }
        List<CompanyAdditionalFieldsDO> companyAdditionalFieldsDOList = companyAdditionalFieldsDAO.selectByExample(example);
        if ("site".equals(companyId)) {
            List<CompanyAdditionalFieldsDO> companyAdditionalFieldsList = new ArrayList<>();
            // 租户级别-模板左侧接口 所有用工单位自定义字段按名称和模块去重
            Map<String, List<CompanyAdditionalFieldsDO>> moduleCodeListMap = companyAdditionalFieldsDOList.parallelStream()
                    .collect(Collectors.groupingBy(CompanyAdditionalFieldsDO::getModuleCode));
            for (String moduleCode : moduleCodeListMap.keySet()) {
                // 先按照创建时间排序
                List<CompanyAdditionalFieldsDO> companyAdditionalFieldList = moduleCodeListMap.get(moduleCode);
                companyAdditionalFieldList = companyAdditionalFieldList.parallelStream()
                        .sorted(Comparator.comparing(BaseCreateDO::getGmtCreate)).collect(Collectors.toList());
                // 再按照字段名称去重
                companyAdditionalFieldList = companyAdditionalFieldList.parallelStream()
                        .filter(distinctByKey(CompanyAdditionalFieldsDO::getFieldName)).collect(Collectors.toList());
                companyAdditionalFieldsList.addAll(companyAdditionalFieldList);
            }
            companyAdditionalFieldsDOList = companyAdditionalFieldsList;
        }
        return companyAdditionalFieldsDOList.parallelStream().map(companyAdditionalFieldsDO -> {
            CompanyAdditionalFieldsListVO companyAdditionalFieldsVO =
                    companyAdditionalFieldsDO.to(CompanyAdditionalFieldsListVO.class);
            // 下拉框放入选项
            if (companyAdditionalFieldsVO.getFieldType() != null && companyAdditionalFieldsVO.getFieldType() == 1) {
                String[] dropDownArray;
                dropDownArray = companyAdditionalFieldsVO.getOptions().split(",");
                companyAdditionalFieldsVO.setDropDownArray(dropDownArray);
            }
            return companyAdditionalFieldsVO;
        }).parallel().collect(Collectors.toList());
    }

    private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
        Map<Object, Boolean> seen = new ConcurrentHashMap<>();
        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }

    @Override
    public List<CompanyAdditionalFieldsVO> selectByCompanyAndModuleCode(String companyId, String moduleCode, String siteId) {
        Example example = new Example(CompanyAdditionalFieldsDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("companyId", companyId)
                .andEqualTo("moduleCode", moduleCode)
                .andEqualTo("siteId", siteId)
                .andIsNull("templateId");
        List<CompanyAdditionalFieldsDO> companyAdditionalFieldsDOList = companyAdditionalFieldsDAO.selectByExample(example);
        if (CollectionUtils.isEmpty(companyAdditionalFieldsDOList)) {
            return new ArrayList<>();
        }
        return companyAdditionalFieldsDOList.stream()
                .map(companyAdditionalFieldsDO -> companyAdditionalFieldsDO.to(CompanyAdditionalFieldsVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public List<CompanyAdditionalFieldsDO> selectByCompanyAndModuleCodes(String companyId, List<String> moduleCodes, String siteId) {
        if (CollectionUtils.isEmpty(moduleCodes)) {
            return new ArrayList<>();
        }
        Example example = new Example(CompanyAdditionalFieldsDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("companyId", companyId)
                .andEqualTo("isOpen", true)
                .andIn("moduleCode", moduleCodes)
                .andIsNull("templateId")
                .andEqualTo("siteId", siteId);
        example.orderBy("sort");
        return companyAdditionalFieldsDAO.selectByExample(example);
    }

    @Override
    public List<CompanyAdditionalFieldsListVO> listByCompanyId(String moduleType, String companyId, String templateId, TokenUser tokenUser) {

        Example example = new Example(CompanyAdditionalFieldsDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("companyId", companyId)
                .andEqualTo("moduleType", moduleType)
                .andEqualTo("siteId", tokenUser.getSiteId());
        if (templateId != null) {
            example.and().andEqualTo("templateId", templateId);
        }
        example.orderBy("sort").orderBy("gmtCreate");
        List<CompanyAdditionalFieldsDO> companyAdditionalFieldsDOS = companyAdditionalFieldsDAO.selectByExample(example);
        if (CollectionUtils.isEmpty(companyAdditionalFieldsDOS)) {
            return new ArrayList<>();
        }
        return companyAdditionalFieldsDOS.stream()
                .map(additionalFieldsDO -> {
                    CompanyAdditionalFieldsListVO fieldsListVO = additionalFieldsDO.to(CompanyAdditionalFieldsListVO.class);
                    if (fieldsListVO.getFieldType() != null && fieldsListVO.getFieldType().equals(FIELD_TYPE_OPTION)) {
                        String[] dropDownArray;
                        dropDownArray = fieldsListVO.getOptions().split(",");
                        fieldsListVO.setDropDownArray(dropDownArray);
                    }
                    return fieldsListVO;
                }).collect(Collectors.toList());
    }

    @Override
    public List<CompanyAdditionalFieldsDO> listByTemplateId(String templateId, TokenUser tokenUser) {
        Example example = new Example(CompanyAdditionalFieldsDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("templateId", templateId)
                .andEqualTo("siteId", tokenUser.getSiteId());
        example.orderBy("sort");
        return companyAdditionalFieldsDAO.selectByExample(example);
    }

    @Override
    public List<CompanyAdditionalFieldsDO> listByTemplateIdList(List<String> templateIdList, TokenUser tokenUser) {
        if (CollectionUtils.isEmpty(templateIdList)) {
            return new ArrayList<>();
        }
        Example example = new Example(CompanyAdditionalFieldsDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andIn("templateId", templateIdList)
                .andEqualTo("siteId", tokenUser.getSiteId());
        example.orderBy("sort");
        return companyAdditionalFieldsDAO.selectByExample(example);
    }

    @Override
    public CompanyAdditionalFieldsDO listBySourceId(Long sourceId, String fieldName, TokenUser tokenUser) {
        Example example = new Example(CompanyAdditionalFieldsDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("sourceId", sourceId)
                .andIsNull("templateId")
                .andEqualTo("siteId", tokenUser.getSiteId());
        List<CompanyAdditionalFieldsDO> companyAdditionalFieldsDOS = companyAdditionalFieldsDAO.selectByExample(example);
        if (CollectionUtils.isEmpty(companyAdditionalFieldsDOS)) {
            return null;
        }
        return companyAdditionalFieldsDOS.get(0);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteForCustom(TokenUser tokenUser, Long companyAdditionalFieldsId) {
        CompanyAdditionalFieldsVO companyAdditionalFieldsVO = selectById(companyAdditionalFieldsId, tokenUser.getSiteId());
        // 只能删除templateId=list的数据
        if (companyAdditionalFieldsVO != null) {
            // 自定义模板模块code
            String moduleCode = companyAdditionalFieldsVO.getModuleType();
            String companyId = companyAdditionalFieldsVO.getCompanyId();
            String fieldName = companyAdditionalFieldsVO.getFieldName();
            // 查询使用此字段的模板，删除字段
            List<CompanyAdditionalFieldsDO> companyAdditionalFieldsDOS = selectByModuleTypeAndFiledName(moduleCode, fieldName, companyId);
            if (!CollectionUtils.isEmpty(companyAdditionalFieldsDOS)) {
                for (CompanyAdditionalFieldsDO companyAdditionalFieldsDO : companyAdditionalFieldsDOS) {
                    if (companyAdditionalFieldsDO.getTemplateId() != null
                            && !companyAdditionalFieldsVO.getTemplateId().equals(HrConstants.ADD_FIELD_COMPANY_SITE)) {
                        deleteByIds(tokenUser, companyAdditionalFieldsDO.getId());
                    }
                }
            }
        }
        return deleteByIds(tokenUser, companyAdditionalFieldsId);
    }

    /**
     * 根据查询参数，构建example
     *
     * @param companyAdditionalFieldsQuery 查询参数
     * @param siteId                       所属站点id
     * @return example
     */
    private Example buildExample(CompanyAdditionalFieldsQuery companyAdditionalFieldsQuery, String siteId) {
        Example example = new Example(CompanyAdditionalFieldsDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        if (companyAdditionalFieldsQuery.getTextLength() != null) {
            example.and().andEqualTo("textLength", companyAdditionalFieldsQuery.getTextLength());
        }
        if (companyAdditionalFieldsQuery.getDescription() != null) {
            example.and().andEqualTo("description", companyAdditionalFieldsQuery.getDescription());
        }
        if (companyAdditionalFieldsQuery.getIsEdit() != null) {
            example.and().andEqualTo("isEdit", companyAdditionalFieldsQuery.getIsEdit());
        }
        if (companyAdditionalFieldsQuery.getModuleCode() != null) {
            example.and().andEqualTo("moduleCode", companyAdditionalFieldsQuery.getModuleCode());
        }
        if (companyAdditionalFieldsQuery.getModuleType() != null) {
            example.and().andEqualTo("moduleType", companyAdditionalFieldsQuery.getModuleType());
        }
        if (companyAdditionalFieldsQuery.getFieldType() != null) {
            example.and().andEqualTo("fieldType", companyAdditionalFieldsQuery.getFieldType());
        }
        if (companyAdditionalFieldsQuery.getFieldName() != null) {
            example.and().andEqualTo("fieldName", companyAdditionalFieldsQuery.getFieldName());
        }
        if (companyAdditionalFieldsQuery.getCompanyId() != null) {
            example.and().andEqualTo("companyId", companyAdditionalFieldsQuery.getCompanyId());
        }
        if (companyAdditionalFieldsQuery.getIsNecessary() != null) {
            example.and().andEqualTo("isNecessary", companyAdditionalFieldsQuery.getIsNecessary());
        }
        if (companyAdditionalFieldsQuery.getIsOpen() != null) {
            example.and().andEqualTo("isOpen", companyAdditionalFieldsQuery.getIsOpen());
        }
        if (companyAdditionalFieldsQuery.getTemplateId() != null) {
            example.and().andEqualTo("templateId", companyAdditionalFieldsQuery.getTemplateId());
        }
        // 排序
        ExampleKit.setExampleOrder(example, companyAdditionalFieldsQuery.getOrders());
        return example;
    }
}




